# -*- coding:utf-8 -*-
"""
@Author : 审心
@Time : 2023/9/27 15:55
sku 监控相关任务
"""
import re
import time
from dataclasses import dataclass
from typing import List, Dict, Optional

from DrissionPage import WebPage

from autoTask.operaitonAid.taobao.product.sku_monitor import tools
from autoTask.operaitonAid.taobao.product.sku_monitor.pojo import SkuItem
from common.logger.log import log_

from common.utils import web_page_util, urlUtil
from common.utils.web_page_util import Tap
from request.utils.request import Request


@dataclass
class SkuMonitor:
    p: WebPage
    ad_id: int
    push_unit_id: int
    product_ids: List[int]

    def __post_init__(self):
        if not self.ad_id:
            log_.error("管理员编号不能为空")
        if not self.push_unit_id:
            log_.error("任务发布单元不能为空")
        if not self.product_ids or len(self.product_ids) == 0:
            log_.error("商品编号列表不能为空")

    def __call__(self):
        log_.info(f"sku 监控任务开始 编号 : {self.product_ids}")
        for item in self.product_ids:
            log_.info(f" 当前商品编号 : {item}")
            self.goto_link(item)
            req_data = None
            # 天猫
            if self.p.url.startswith("https://detail.tmall.com/"):
                req_data = self.get_tm_sku_content()
            # 淘宝
            elif self.p.url.startswith("https://item.taobao.com/"):
                req_data = self.get_tb_sku_content()
            else:
                log_.error(f"非 天猫/淘宝 商品 链接 : {self.p.url}")
            if not req_data:
                log_.warning(f"未成功获取构建请求对象 商品编号 ：{item}")
            #  提交数据
            self.commit_data(req_data)

    def get_tm_sku_content(self) -> Optional[Dict]:
        """
        获取天猫 sku 相关信息
        :return:
        """
        match = re.search(r'id=(\d+)', self.p.url)
        if not match:
            log_.warning(f"url中未匹配到商品编号 url : {self.p.url}")
            return None
        product_id = match.group(1)
        es = self.p("x://span[.='颜色分类：']").next().eles(".:skuValueName")
        # 过滤不能点击的元素
        es = [e for e in es if "disableSkuText" not in e.attr("class")]
        sku_list: List[SkuItem] = []
        for e in es:
            if e.states.is_covered:
                self.covered_handle()
            Tap(e, is_random=False, after_delay=[1, 2])()
            match = re.search(r'skuId=(\d+)', self.p.url)
            if not match:
                log_.warning(f"url 中 未匹配到 skuId url : {self.p.url}")
                continue
            # sku编号, sku正文, 价格
            sku_id, sku_content, price = match.group(1), e.text, None
            # 价格
            te = self.p("css:Price--extraPriceText--2dbLkGw", timeout=0)
            if not te:
                te = self.p("css:Price--priceText--2nLbVda", timeout=0)
            if te:
                price = float(te.text)
            sku_list.append(SkuItem(sku_id, sku_content, price))
        return self.builder_req_data(product_id, sku_list)

    def get_tb_sku_content(self) -> Optional[Dict]:
        """
        获取淘宝 sku 相关信息
        :return:
        """
        match = re.search(r'id=(\d+)', self.p.url)
        if not match:
            log_.warning(f"url中未匹配到商品编号 url : {self.p.url}")
            return None
        product_id = match.group(1)
        es = self.p("css:tb-img").eles("tag:li")
        sku_list: List[SkuItem] = []
        for e in es:
            if e.states.is_covered:
                self.covered_handle()
            Tap(e, is_random=False, after_delay=[1, 2])()
            # sku编号, sku正文, 价格
            sku_id, sku_content, price = int(e.attr("data-value").split(":")[1]), None, None
            # 价格
            t = self.p("#J_PromoPriceNum", timeout=0)
            if not t:
                t = self.p("css:tb-rmb-num", timeout=0)
            if t:
                price = float(t.text)
            # 正文
            t = e("tag:span", timeout=0)
            if t:
                sku_content = t.text
            sku_list.append(SkuItem(sku_id, sku_content, price))
        return self.builder_req_data(product_id, sku_list)

    def builder_req_data(self, product_id, sku_list: List[SkuItem]) -> Optional[Dict]:
        """
        构建商品的请求自带你
        :param product_id: 商品编号
        :param sku_list: sku 信息列表
        :return: 请求数据
        """
        if len(sku_list) == 0:
            log_.warning(f" 商品 : {product_id} , 没有获取到任何 sku")
            return None
        # 去除 sku id 重复的 sku (保留索引靠前的)
        unique_sku_items = {}
        for item in sku_list:
            if item.id not in unique_sku_items:
                unique_sku_items[item.id] = item
        if len(sku_list) != len(unique_sku_items):
            log_.warning(f"存在 skuId 重复的 sku \n 原列 : {sku_list}")
            sku_list = list(unique_sku_items.values())
        result = {
            "adId": self.ad_id,
            "pushUnitId": self.push_unit_id,
            "productId": product_id,
            "dateItemList": [{
                "skuId": sku.id,
                "skuContent": sku.content,
                "price": sku.price,
            } for sku in sku_list if sku.check_attr()]
        }
        return result

    def commit_data(self, req_data: Dict):
        """
        提交数据
        :param req_data: 请求数据
        :return:
        """
        result = Request("post", "operationAid/product/monitor-record/public/robot-commit",
                         req_title="商品监控数据", json_data=req_data).send()
        log_.info(f" 提交数据结果 ： {result}")
        if result.get("code") != 0:
            raise RuntimeError(f"提交数据时失败 : {result.get('result')}")

    def goto_link(self, product_id):
        self.p.get(f"https://item.taobao.com/item.htm?id={product_id}")
        self.p.wait.load_complete(timeout=60)
        time.sleep(3)

    def covered_handle(self):
        """
        覆盖对话窗处理
        :return:
        """
        e = self.p(".baxia-dialog-close", timeout=3)
        if e:
            Tap(e, after_delay=[3, 5])()


if __name__ == '__main__':
    p = web_page_util.create_page(is_refresh=False)
    o = SkuMonitor(p=p, ad_id=1, push_unit_id=6, product_ids=[728558231670, 728558231670])
    o()
